home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / dev / misc / AmigaSDLsrc.lha / amisrc / SDL_rwops.c < prev    next >
C/C++ Source or Header  |  2001-04-29  |  7KB  |  275 lines

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
  4.  
  5.     This library is free software; you can redistribute it and/or
  6.     modify it under the terms of the GNU Library General Public
  7.     License as published by the Free Software Foundation; either
  8.     version 2 of the License, or (at your option) any later version.
  9.  
  10.     This library is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.     Library General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU Library General Public
  16.     License along with this library; if not, write to the Free
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19.     Sam Lantinga
  20.     slouken@devolution.com
  21. */
  22.  
  23. #ifdef SAVE_RCSID
  24. static char rcsid =
  25.  "@(#) $Id: SDL_rwops.c,v 1.3.2.8 2001/02/10 07:20:04 hercules Exp $";
  26. #endif
  27.  
  28. /* This file provides a general interface for SDL to read and write
  29.    data sources.  It can easily be extended to files, memory, etc.
  30. */
  31.  
  32. #include <stdlib.h>
  33. #include <string.h>
  34.  
  35. #include "SDL_error.h"
  36. #include "SDL_rwops.h"
  37.  
  38. /* Functions to read/write stdio file pointers */
  39.  
  40. static int stdio_seek(SDL_RWops *context, int offset, int whence)
  41. {
  42.     if ( fseek(context->hidden.stdio.fp, offset, whence) == 0 ) {
  43.         return(ftell(context->hidden.stdio.fp));
  44.     } else {
  45.         SDL_Error(SDL_EFSEEK);
  46.         return(-1);
  47.     }
  48. }
  49. static int stdio_read(SDL_RWops *context, void *ptr, int size, int maxnum)
  50. {
  51.     size_t nread;
  52.  
  53.     nread = fread(ptr, size, maxnum, context->hidden.stdio.fp); 
  54.     if ( nread == 0 && ferror(context->hidden.stdio.fp) ) {
  55.         SDL_Error(SDL_EFREAD);
  56.     }
  57.     return(nread);
  58. }
  59. static int stdio_write(SDL_RWops *context, const void *ptr, int size, int num)
  60. {
  61.     size_t nwrote;
  62.  
  63.     nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp);
  64.     if ( nwrote == 0 && ferror(context->hidden.stdio.fp) ) {
  65.         SDL_Error(SDL_EFWRITE);
  66.     }
  67.     return(nwrote);
  68. }
  69. static int stdio_close(SDL_RWops *context)
  70. {
  71.     if ( context ) {
  72.         if ( context->hidden.stdio.autoclose ) {
  73.             /* WARNING:  Check the return value here! */
  74.             fclose(context->hidden.stdio.fp);
  75.         }
  76.         free(context);
  77.     }
  78.     return(0);
  79. }
  80.  
  81. /* Functions to read/write memory pointers */
  82.  
  83. static int mem_seek(SDL_RWops *context, int offset, int whence)
  84. {
  85.     Uint8 *newpos;
  86.  
  87.     switch (whence) {
  88.         case SEEK_SET:
  89.             newpos = context->hidden.mem.base+offset;
  90.             break;
  91.         case SEEK_CUR:
  92.             newpos = context->hidden.mem.here+offset;
  93.             break;
  94.         case SEEK_END:
  95.             newpos = context->hidden.mem.stop+offset;
  96.             break;
  97.         default:
  98.             SDL_SetError("Unknown value for 'whence'");
  99.             return(-1);
  100.     }
  101.     if ( newpos < context->hidden.mem.base ) {
  102.         newpos = context->hidden.mem.base;
  103.     }
  104.     if ( newpos > context->hidden.mem.stop ) {
  105.         newpos = context->hidden.mem.stop;
  106.     }
  107.     context->hidden.mem.here = newpos;
  108.     return(context->hidden.mem.here-context->hidden.mem.base);
  109. }
  110. static int mem_read(SDL_RWops *context, void *ptr, int size, int maxnum)
  111. {
  112.     int num;
  113.  
  114.     num = maxnum;
  115.     if ( (context->hidden.mem.here + (num*size)) > context->hidden.mem.stop ) {
  116.         num = (context->hidden.mem.stop-context->hidden.mem.here)/size;
  117.     }
  118.     memcpy(ptr, context->hidden.mem.here, num*size);
  119.     context->hidden.mem.here += num*size;
  120.     return(num);
  121. }
  122. static int mem_write(SDL_RWops *context, const void *ptr, int size, int num)
  123. {
  124.     if ( (context->hidden.mem.here + (num*size)) > context->hidden.mem.stop ) {
  125.         num = (context->hidden.mem.stop-context->hidden.mem.here)/size;
  126.     }
  127.     memcpy(context->hidden.mem.here, ptr, num*size);
  128.     context->hidden.mem.here += num*size;
  129.     return(num);
  130. }
  131. static int mem_close(SDL_RWops *context)
  132. {
  133.     if ( context ) {
  134.         free(context);
  135.     }
  136.     return(0);
  137. }
  138.  
  139. /* Functions to create SDL_RWops structures from various data sources */
  140. #ifdef WIN32
  141. /* Aggh.  You can't (apparently) open a file in an application and
  142.    read from it in a DLL.
  143. */
  144. static int in_sdl = 0;
  145. #endif
  146.  
  147. #ifdef macintosh
  148. /*
  149.  * translate unix-style slash-separated filename to mac-style colon-separated
  150.  * name; return malloced string
  151.  */
  152. static char *unix_to_mac(const char *file)
  153. {
  154.     int flen = strlen(file);
  155.     char *path = malloc(flen + 2);
  156.     const char *src = file;
  157.     char *dst = path;
  158.     if(*src == '/') {
  159.         /* really depends on filesystem layout, hope for the best */
  160.         src++;
  161.     } else {
  162.         /* Check if this is a MacOS path to begin with */
  163.         if(*src != ':')
  164.             *dst++ = ':';   /* relative paths begin with ':' */
  165.     }
  166.     while(src < file + flen) {
  167.         const char *end = strchr(src, '/');
  168.         int len;
  169.         if(!end)
  170.             end = file + flen; /* last component */
  171.         len = end - src;
  172.         if(len == 0 || (len == 1 && src[0] == '.')) {
  173.             /* remove repeated slashes and . */
  174.         } else {
  175.             if(len == 2 && src[0] == '.' && src[1] == '.') {
  176.                 /* replace .. with the empty string */
  177.             } else {
  178.                 memcpy(dst, src, len);
  179.                 dst += len;
  180.             }
  181.             if(end < file + flen)
  182.                 *dst++ = ':';
  183.         }
  184.         src = end + 1;
  185.     }
  186.     *dst++ = '\0';
  187.     return path;
  188. }
  189. #endif /* macintosh */
  190.  
  191. SDL_RWops *SDL_RWFromFile(const char *file, const char *mode)
  192. {
  193.     FILE *fp;
  194.     SDL_RWops *rwops;
  195.  
  196.     rwops = NULL;
  197.  
  198. #ifdef macintosh
  199.     {
  200.         char *mpath = unix_to_mac(file);
  201.         fp = fopen(mpath, mode);
  202.         free(mpath);
  203.     }
  204. #else
  205.     fp = fopen(file, mode);
  206. #endif
  207.     if ( fp == NULL ) {
  208.         SDL_SetError("Couldn't open %s", file);
  209.     } else {
  210. #ifdef WIN32
  211.         in_sdl = 1;
  212.         rwops = SDL_RWFromFP(fp, 1);
  213.         in_sdl = 0;
  214. #else
  215.         rwops = SDL_RWFromFP(fp, 1);
  216. #endif
  217.     }
  218.     return(rwops);
  219. }
  220.  
  221. SDL_RWops *SDL_RWFromFP(FILE *fp, int autoclose)
  222. {
  223.     SDL_RWops *rwops;
  224.  
  225. #ifdef WIN32
  226.     if ( ! in_sdl ) {
  227.         SDL_SetError("You can't pass a FILE pointer to a DLL (??)");
  228.         /*return(NULL);*/
  229.     }
  230. #endif
  231.     rwops = SDL_AllocRW();
  232.     if ( rwops != NULL ) {
  233.         rwops->seek = stdio_seek;
  234.         rwops->read = stdio_read;
  235.         rwops->write = stdio_write;
  236.         rwops->close = stdio_close;
  237.         rwops->hidden.stdio.fp = fp;
  238.         rwops->hidden.stdio.autoclose = autoclose;
  239.     }
  240.     return(rwops);
  241. }
  242.  
  243. SDL_RWops *SDL_RWFromMem(void *mem, int size)
  244. {
  245.     SDL_RWops *rwops;
  246.  
  247.     rwops = SDL_AllocRW();
  248.     if ( rwops != NULL ) {
  249.         rwops->seek = mem_seek;
  250.         rwops->read = mem_read;
  251.         rwops->write = mem_write;
  252.         rwops->close = mem_close;
  253.         rwops->hidden.mem.base = (Uint8 *)mem;
  254.         rwops->hidden.mem.here = rwops->hidden.mem.base;
  255.         rwops->hidden.mem.stop = rwops->hidden.mem.base+size;
  256.     }
  257.     return(rwops);
  258. }
  259.  
  260. SDL_RWops *SDL_AllocRW(void)
  261. {
  262.     SDL_RWops *area;
  263.  
  264.     area = (SDL_RWops *)malloc(sizeof *area);
  265.     if ( area == NULL ) {
  266.         SDL_OutOfMemory();
  267.     }
  268.     return(area);
  269. }
  270.  
  271. void SDL_FreeRW(SDL_RWops *area)
  272. {
  273.     free(area);
  274. }
  275.